package org.space.galaxyCabinet.config;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.space.galaxyCabinet.RabbitMQUtil;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.retry.support.RetryTemplate;
import org.springframework.stereotype.Component;

@Slf4j
@Component
@Data
@ConfigurationProperties(prefix = "spring.rabbitmq")
public class RabbitMQConfig {

    private String host;
    private String username;
    private String password;
    private boolean publisherReturns;
    private String publisherConfirmType;
    private String virtualHost ;

    @Autowired
    private RetryTemplate rabbitRetryTemplate;


    @Bean
    public ConnectionFactory connectionFactory() {
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory(host);
        connectionFactory.setUsername(username);
        connectionFactory.setPassword(password);
        // 开启发送确认
        connectionFactory.setPublisherConfirmType(CachingConnectionFactory.ConfirmType.CORRELATED);
        // 开启发送返回
        connectionFactory.setPublisherReturns(true);
        return connectionFactory;
    }


    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
        RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);

        // 消息确认回调
        rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
            if (correlationData != null) {
                if (ack) {
                    log.info("消息确认成功，ID: {}", correlationData.getId());
                } else {
                    log.error("消息确认失败，ID: {}, 原因: {}", correlationData.getId(), cause);
                    // 这里可以添加消息重试逻辑
                    rabbitRetryTemplate.execute(retryContext -> {
                        int retryCount = retryContext.getRetryCount();
                        log.info("开始第{}次重试，消息ID: {}", retryCount + 1, correlationData.getId());

                        rabbitTemplate.send(correlationData.getReturned().getMessage());
                        log.info("重试发送成功，消息ID: {}", correlationData.getId());
                        return null;
                    });
                }
            }
        });

        // 消息返回回调
        rabbitTemplate.setReturnsCallback(returned -> {
            log.error("消息返回，交换机: {}, 路由键: {}, 回复码: {}, 回复文本: {}, 消息: {}",
                returned.getExchange(),
                returned.getRoutingKey(),
                returned.getReplyCode(),
                returned.getReplyText(),
                new String(returned.getMessage().getBody()));
            // 处理无法路由的消息
        });
        return rabbitTemplate;
    }
}


